package com.le.tester.javaThink.fourth.concurrency;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * createTime：2021/11/29 16:16
 * description：当notifyAll因为某个特定锁而被调用时，只有等待这个任务的锁会被唤醒
 */

class Blocker {
    synchronized void waitingCall() {
        try {
            while (!Thread.interrupted()) {
                wait();
                System.out.println(Thread.currentThread().getName() + ",");
            }
        } catch (InterruptedException e) {
            System.out.println("发生了中断的异常");
        }
    }

    //通过synch来唤醒特定的锁
    synchronized void prod() {
        notify();
    }

    synchronized void prodAll() {
        notifyAll();
    }
}

//任务等待唤醒
class Task implements Runnable {

    static Blocker blocker = new Blocker();

    @Override
    public void run() {
        //进入了synchronized
        //等待
        blocker.waitingCall();
    }
}

//同task
class Task2 implements Runnable {

    static Blocker blocker = new Blocker();

    //等待
    @Override
    public void run() {
        blocker.waitingCall();
    }
}

public class NotifyVsNotifyAll {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            service.execute(new Task());
        }
        service.execute(new Task2());
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            boolean prod = true;

            @Override
            public void run() {
                if (prod) {
                    System.out.println("notify()");
                    Task.blocker.prod();
                    prod = false;
                } else {
                    System.out.println("notifyAll()");
                    Task.blocker.prodAll();
                    prod = true;
                }
            }
            //延迟400ms，每隔400ms执行一次
        }, 400, 400);
        TimeUnit.SECONDS.sleep(5);
        timer.cancel();
        System.out.println("timer canceled");
        TimeUnit.MILLISECONDS.sleep(500);
        System.out.println("shutting down");
        service.shutdownNow();
    }
}
